package com.snail.cloud.controller;

import com.google.gson.Gson;
import com.snail.cloud.config.JwtTokenUtil;
import com.snail.cloud.config.MobilePhoneVerificationCodeAuthenticationToken;
import com.snail.cloud.dao.IotUserMapper;
import com.snail.cloud.model.BasePageInfo;
import com.snail.cloud.model.IotUser;
import com.snail.cloud.model.ResultData;
import com.snail.cloud.model.UserDetailsImpl;
import com.snail.cloud.model.vo.IotUserVo;
import com.snail.cloud.model.vo.UserInsertVo;
import com.snail.cloud.model.vo.UserUpdateVo;
import com.snail.cloud.service.UserService;
import com.snail.cloud.util.SendSmsUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.util.Collection;

import static com.snail.cloud.model.ResultCodeEnum.BAD_REQUEST;
import static com.snail.cloud.model.ResultCodeEnum.SMD_SEND_FAILED;
import static com.snail.cloud.util.SendSmsUtil.PREFIX_CODE;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * 用户接口
 * @author MR.LHL
 * @date 2024/2/27
 */
@RestController
public class UserController {
    private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserService userService;
    @Autowired
    private IotUserMapper iotUserMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @GetMapping("/hello")
    public Object hello() {
        Collection<? extends GrantedAuthority> authorities = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
        System.out.println(authorities);
        IotUserVo snail = iotUserMapper.selectUserVoByUsername("snail");
        return snail;

    }

    @GetMapping("/hello1")
    public void hello1() {
        UserDetails snail = userService.loadUserByUsername("snail");
        System.out.println(snail);
    }

    @GetMapping("/hello2")
    @PreAuthorize("hasRole('ROLE_admin')")
    public Object hello2() {
        IotUser snail = iotUserMapper.selectByUsername("snail");
        return ResultData.success(snail);
    }

    @PostMapping("/user/register")
    public Object userRegister(@RequestBody UserInsertVo iotUser) {
        ResultData resultData = userService.userAdd(iotUser);
        return resultData;
    }

    @PostMapping("/user/login")
    public Object login(@RequestBody IotUser loginRequest, HttpServletResponse response) {
        Authentication authenticationRequest =
                UsernamePasswordAuthenticationToken.unauthenticated(loginRequest.getUsername(), loginRequest.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationRequest);
        if (authentication == null) {
            throw new RuntimeException("Login false");
        }
        UserDetailsImpl securityUser = (UserDetailsImpl) authentication.getPrincipal();
        Long useId = securityUser.getIotUser().getUserId();
        String usrName = securityUser.getUsername();
        String jwt = JwtTokenUtil.generateToken(securityUser);
        response.setHeader("token", jwt);
        return ResultData.success(securityUser.getIotUser());
    }

    @PostMapping("/user/code/login")
    public Object loginCode(@RequestBody IotUser loginRequest, HttpServletResponse response) {
        Authentication authenticationRequest =
                new MobilePhoneVerificationCodeAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());
        Authentication authentication = authenticationManager.authenticate(authenticationRequest);
        if (authentication == null) {
            throw new RuntimeException("Login false");
        }
        UserDetailsImpl securityUser = (UserDetailsImpl) authentication.getPrincipal();
        String jwt = JwtTokenUtil.generateToken(securityUser);
        response.setHeader("token", jwt);
        return ResultData.success(securityUser.getIotUser());
    }

    @PostMapping("/user/password/update")
    public Object passwordUpdate(@RequestBody UserUpdateVo user, HttpServletRequest request, HttpServletResponse response) {
        String token = request.getHeader("token");
        ResultData resultData = userService.passwordUpdate(user, token);
        return resultData;
    }

    @PostMapping("/user/password/forget")
    public Object passwordForget(@RequestBody UserInsertVo user, HttpServletRequest request, HttpServletResponse response) {
        ResultData resultData = userService.passwordForget(user);
        return resultData;
    }


    /**
     * 通用发送短信（不带业务逻辑）
     */
    @RequestMapping(value = {"/snail/user/phone/sendsms"}, method = POST)
    public Object commonSendSms(@RequestBody UserInsertVo reqData, HttpServletResponse response) {
        LOGGER.info("==========>[/snail/user/phone/sendsms] ,reqData={}", new Gson().toJson(reqData));
        String phone = reqData.getPhone();
        if (StringUtils.isBlank(phone)) {
            LOGGER.error("==========>[参数错误] mobileNumber不能为空");
            return ResultData.error(BAD_REQUEST);
        }
        String code = SendSmsUtil.generateVerificationCode();
        boolean sendResponse = SendSmsUtil.sendSms(code, phone);
        if (sendResponse) {
            redisTemplate.opsForValue().set(PREFIX_CODE + phone, code, Duration.ofMinutes(10));
            LOGGER.info("==========>[发送短信成功],phone:{}，code:{}", phone, code);
            return ResultData.success();
        }
        LOGGER.error("==========>[发送短信失败] phone={}", phone);
        return ResultData.error(SMD_SEND_FAILED);
    }

    @PostMapping(value = "/user/qurey/page")
    public Object qureyPage(@RequestBody BasePageInfo pageInfo) {
        ResultData resultData = userService.getUserPage(pageInfo);
        return resultData;
    }
}